#ifndef __core_widget_h__
#define __core_widget_h__

#include "base/def.h"

#include "core/object.h"
#include "core/attribute.hpp"
#include "core/style.h"
#include "core/const.h"

#include "xml/xml.h"

#include <vector>
#include <windows.h>

namespace core
{
    enum Message
    {
        ST_LAYOUT,
        ST_PAINT,
        ST_MOUSEHOVER,
        ST_MOUSELEAVE,
        ST_LBUTTONDOWN,
        ST_LBUTTONUP,
        ST_MOUSEWHEEL,
        ST_RBUTTONDOWN,
        ST_RBUTTONUP,
        ST_KEYDOWN,
        ST_KEYUP,
        ST_CHAR
    };

    #define BEGIN_MESSAGE_MAP()\
        virtual bool ProcessMessage(UINT umsg, WPARAM wparam, LPARAM lparam, LRESULT* lresult)\
        {\
            if (lresult)\
                *lresult = 0;\
            bool handled = false;\
            LRESULT result = 0;

    #define END_MESSAGE_MAP()\
            if (lresult)\
                *lresult = result;\
            return handled;\
        }

    #define MESSAGE_HANDLE(msg, func)\
        if (msg == umsg)\
        {\
            handled = true;\
            result = func(wparam, lparam, &handled);\
        }\
        else

    #define CHAIN_MESSAGE_MAP(theclass)\
        if (theclass::ProcessMessage(umsg, wparam, lparam, &result))\
        {\
            handled = true;\
        }\
        else


    class StWidget : public StAttributeSet
    {
    public:
        friend class StContainer;
        DECLARE_ATTRIBUTE_MAP();

        StWidget();
        ~StWidget();

        virtual KeyWidget Key();
        virtual bool IsContainer();
        virtual StObject* Clone();
        virtual void Drop();
        virtual StWidget* HitTest(int x, int y);
        virtual bool Parse(const XmlElement* element, const StStyleCache& cache);

        LRESULT DispatchMessage(UINT umsg, WPARAM wparam, LPARAM lparam);

        const std::string&  TagName() { return tag_name_; }
        void SetTagName(const std::string &name) { tag_name_ = name; }

    protected:
        bool ParseAttribute(const XmlElement* element, const StStyleCache& cache);
        bool AnalyseStyle(const char *value, const char *classname, const StStyleCache& cache);

        void CopyToWidget(StWidget* target);

    protected:
        BEGIN_MESSAGE_MAP()
        END_MESSAGE_MAP()

    protected:
        StStyle        style_normal_;
        StStyle        style_hover_;
        StStyle        style_down_;

        RECT           rect_border_;
        RECT           rect_content_;
        ActionState    action_state_;
        std::string    tag_name_;

    public:
        StWidget* Parent()          { return parent_; }
        StWidget* PreviousSibling() { return prev_; }
        StWidget* NextSibling()     { return next_; }

    protected:
        StWidget* parent_;
        StWidget* prev_;
        StWidget* next_;

    private:
        DISABLE_COPY_AND_ASSIGN(StWidget)
    };
}

#endif